/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.service.contract.impl;

import com.alibaba.fastjson2.JSONObject;
import com.je.common.base.service.CommonService;
import com.je.common.base.util.TreeUtil;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.meta.model.dd.DicInfoVo;
import com.je.meta.service.contract.ContractService;
import org.apache.commons.lang.StringUtils;
import org.apache.servicecomb.registry.DiscoveryManager;
import org.apache.servicecomb.registry.RegistrationManager;
import org.apache.servicecomb.registry.api.registry.Microservice;
import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
import org.apache.servicecomb.registry.api.registry.MicroserviceInstances;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service(value = "contractService")
public class ContractServiceImpl implements ContractService {
    @Autowired
    private CommonService commonService;

    public static final String ROOT_ID = "ROOT";

    @Override
    public JSONTreeNode getMicroservices(DicInfoVo dicInfoVo) {
        List<JSONTreeNode> jsonTreeNodeList = new ArrayList<>();
        //构建root
        jsonTreeNodeList.add(buildRootNode(ROOT_ID));
        //获取所有的服务
        List<Microservice> microservices = DiscoveryManager.INSTANCE.getAllMicroservices();
        Collections.sort(microservices, Comparator.comparing(Microservice::getServiceName));
        Map<String, JSONTreeNode> appInfo = new HashMap<>();
        for (Microservice microservice : microservices) {
            if (appInfo.get(microservice.getAppId()) == null) {
                //构建二级树appId
                jsonTreeNodeList.add(buildTreeNode(microservice.getAppId(), ROOT_ID));
                appInfo.put(microservice.getAppId(), buildTreeNode(microservice.getAppId(), ROOT_ID));
            }
            buildThreeChild(microservice, jsonTreeNodeList, appInfo);
        }
        return commonService.buildJSONNewTree(jsonTreeNodeList, ROOT_ID);
    }

    private void buildThreeChild(Microservice microservice, List<JSONTreeNode> jsonTreeNodeList, Map<String, JSONTreeNode> appInfo) {
        //构建三级树
        JSONTreeNode jsonTreeNode = new JSONTreeNode();
        jsonTreeNode.setCode(microservice.getServiceName());
        jsonTreeNode.setText(microservice.getServiceName());
        jsonTreeNode.setId(microservice.getServiceId());
        jsonTreeNode.setNodeType("LEAF");
        jsonTreeNode.setExpanded(true);
        jsonTreeNode.setParent(microservice.getAppId());
        jsonTreeNode.setNodeInfo("");
        jsonTreeNodeList.add(jsonTreeNode);
        if (appInfo.get(microservice.getAppId() + microservice.getServiceName()) == null) {
            buildInstanceListTree(microservice, getInstancesByServiceInfo(microservice), jsonTreeNodeList);
            appInfo.put(microservice.getAppId() + microservice.getServiceName(), new JSONTreeNode());
        }
    }

    private void buildInstanceListTree(Microservice microservice, List<MicroserviceInstance> instanceList, List<JSONTreeNode> jsonTreeNodeList) {
        //构建四级树
        for (MicroserviceInstance instance : instanceList) {
            JSONTreeNode instanceTree = new JSONTreeNode();
            instanceTree.setCode(instance.getInstanceId());
            instanceTree.setText(StringUtils.join(instance.getEndpoints(), ","));
            instanceTree.setId(instance.getInstanceId());
            instanceTree.setNodeType("LEAF");
            instanceTree.setParent(instance.getServiceId());
            JSONObject nodeInfo = new JSONObject();
            nodeInfo.put("isInstance", true);
            nodeInfo.put("serviceName", microservice.getServiceName());
            nodeInfo.put("instanceId", instance.getInstanceId());
            if (microservice.getServiceName().equals("gateway")) {
                nodeInfo.put("getUrl", "/je/gateway/contract/load");
                nodeInfo.put("clearUrl", "/je/gateway/contract/remove");
            } else {
                nodeInfo.put("getUrl", "/je/meta/rpcContract/load");
                nodeInfo.put("clearUrl", "/je/meta/rpcContract/remove");
            }
            JSONObject headers = new JSONObject();
            headers.put("pd", microservice.getServiceName());
            headers.put("x-service-instance", instance.getInstanceId());
            nodeInfo.put("headers", headers);
            instanceTree.setNodeInfo(nodeInfo.toJSONString());
            jsonTreeNodeList.add(instanceTree);
        }
    }

    private JSONTreeNode buildRootNode(String id) {
        JSONTreeNode root = TreeUtil.buildRootNode();
        root.setId(id);
        root.setExpandable(true);
        root.setExpanded(false);
        root.setLayer("0");
        root.setNodeInfo("");
        root.setLeaf(false);
        return root;
    }

    private JSONTreeNode buildTreeNode(String id, String parentId) {
        JSONTreeNode instanceTree = new JSONTreeNode();
        instanceTree.setCode(id);
        instanceTree.setText(id);
        instanceTree.setId(id);
        instanceTree.setExpanded(true);
        instanceTree.setNodeType("LEAF");
        instanceTree.setParent(parentId);
        instanceTree.setNodeInfo("");
        return instanceTree;
    }

    private List<MicroserviceInstance> getInstancesByServiceInfo(Microservice microservice) {
        String appId = microservice.getAppId();
        String serviceName = microservice.getServiceName();
        String versionRule = microservice.getVersion();
        try {
            MicroserviceInstances instances = DiscoveryManager.INSTANCE.findServiceInstances(appId, serviceName,versionRule);
            return instances.getInstancesResponse().getInstances();
        } catch (NullPointerException nullPointerException) {
            return new ArrayList<>();
        }
    }
}
